using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using JigLibX.Physics;
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;

namespace fizyka
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Model kostka1, kostka2;
        Effect efekt , efekt2;
        Matrix cam,cam2;
        Matrix model,model2;
        Matrix projection,projection2;
        PhysicsSystem PhySystem;
        Box box1, box2;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here


            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {


            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            kostka1 = Content.Load<Model>("box");
            //kostka2 = Content.Load<Model>("box");
            efekt = Content.Load<Effect>("Effect");
           // efekt2 = Content.Load<Effect>("Effect");
//
            efekt.CurrentTechnique = efekt.Techniques["Technique1"];
            //efekt2.CurrentTechnique = efekt2.Techniques["Technique1"];

            foreach (var mm in kostka1.Meshes)
                for (int j = 0; j < mm.MeshParts.Count; j++)
                    mm.MeshParts[j].Effect = efekt;

            PhySystem = new JigLibX.Physics.PhysicsSystem();
            PhySystem.CollisionSystem = new JigLibX.Collision.CollisionSystemSAP();

            JigLibX.Physics.Body body1 = new JigLibX.Physics.Body();
            JigLibX.Physics.Body body2 = new JigLibX.Physics.Body();

            JigLibX.Collision.CollisionSkin m_skin1 = new CollisionSkin(body1);
            body1.CollisionSkin = m_skin1;

            JigLibX.Collision.CollisionSkin m_skin2 = new CollisionSkin(body2);
            body2.CollisionSkin = m_skin2;

            box1 = new Box(Vector3.One * 0.5f, Matrix.Identity, Vector3.One);
            m_skin1.AddPrimitive(box1, new MaterialProperties(0.8f, 0.8f, 0.7f));

            box2 = new Box(Vector3.One * 0.5f, Matrix.Identity, Vector3.One);
            m_skin1.AddPrimitive(box2, new MaterialProperties(0.8f, 0.8f, 0.7f));

            Vector3 position1 = new Vector3(0, 5.0f, 0);
            body1.MoveTo(position1, Matrix.Identity);
            body1.EnableBody();


            Vector3 position2 = new Vector3(0, 0, 0);
            body2.MoveTo(position2, Matrix.Identity);
            body2.EnableBody();

            //SetMass();
            //SetMass();

            body2.Immovable = true;

            //foreach (var mm in kostka2.Meshes)
             //   for (int j = 0; j < mm.MeshParts.Count; j++)
             //       mm.MeshParts[j].Effect = efekt2;

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            PhySystem.Integrate(0.01f);

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            //setCamera();

            //efekt.Begin();
            //efekt.CurrentTechnique.Passes[0].Begin();

            cam = Matrix.CreateLookAt(new Vector3(15, 15, 15), Vector3.Zero, Vector3.Up);
            projection = Matrix.CreatePerspectiveFieldOfView(1.5f, 1.2f, 1, 10000);



            efekt.Parameters["World"].SetValue(Matrix.CreateTranslation(box1.Position));
            efekt.Parameters["View"].SetValue(cam);
            efekt.Parameters["Projection"].SetValue(projection);

            foreach (var mm in kostka1.Meshes)
                mm.Draw();


            //efekt.Parameters["World"].SetValue(Matrix.CreateTranslation(new Vector3(0, 5, 0)));
            efekt.Parameters["World"].SetValue(Matrix.CreateTranslation(box2.Position));
            foreach (var mm in kostka1.Meshes)
                mm.Draw();
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
        public void setCamera()
        {
            //model1 = Matrix.CreateFromYawPitchRoll(0, 0, 0);
            //cam1 = Matrix.CreateLookAt(new Vector3(15, 15, 15), Vector3.Zero, Vector3.Up);
            //projection1= Matrix.CreatePerspectiveFieldOfView(1.5f, 1.2f, 1, 10000);

            //model2 = Matrix.CreateFromYawPitchRoll(0, 0, 0);
            //cam2 = Matrix.CreateLookAt(new Vector3(15, 15, 15), Vector3.Zero, Vector3.Up);
            //projection2 = Matrix.CreatePerspectiveFieldOfView(1.5f, 1.2f, 1, 10000);

            //efekt1.Parameters["World"].SetValue(Matrix.CreateTranslation(new Vector3(0, 5, 0)));
            //efekt1.Parameters["View"].SetValue(cam1);
            //efekt1.Parameters["Projection"].SetValue(projection1);



            //efekt1.Parameters["WVP"].SetValue(model * cam * projection);
            //efekt2.Parameters["WVP"].SetValue(model * cam * projection);
            //efekt.Parameters["UserTexture"].SetValue(tex);

        }
        private void SetMass(Body body, CollisionSkin skin, float mass)
        {
            PrimitiveProperties primitiveProperties = new PrimitiveProperties(
            PrimitiveProperties.MassDistributionEnum.Solid,
            PrimitiveProperties.MassTypeEnum.Mass, mass);
            float junk;
            Vector3 com;
            Matrix it;
            Matrix itCoM;
            skin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM);
            body.BodyInertia= itCoM;
            body.Mass= junk;
            skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity));
        }
    }
}
